ifndef SRC
$(warning warning: SRC is not specified (ignore this warning if the benchmark overwrites the build targets.))
endif

ifndef HONGG_SRC
$(error HONGG_SRC is not specified. Run: `$ export HONGG_SRC=/path/to/honggfuzz/src`)
endif

CFLAGS += $(if $(OPT),$(OPT),-O3) -ggdb
LDFLAGS += $(if $(OPT),$(OPT),-O3) -ggdb

.SUFFIXES:  # disable built-in rules
.PHONY: all

all: sf

# Native builds
CC = /usr/bin/clang
CXX = /usr/bin/clang++
NATIVE_FLAGS :=
NATIVE_LDFLAGS :=

native: $(addsuffix .o, $(SRC))
	$(CC) $(LDFLAGS) $(NATIVE_LDFLAGS) $? -o $@

%.o: %.c
	$(CC) $(CFLAGS) $(NATIVE_FLAGS) $< -c -o $@


# Native with coverage
CCSF = /usr/bin/clang-sf
CXXSF = /usr/bin/clang-sf++
NATIVECOV_FLAGS := --coverage-only hongg
NATIVECOV_LDFLAGS := --coverage-only hongg

nativecov: $(addsuffix .nativecov.o, $(SRC))
	$(CCSF) $(LDFLAGS) $(NATIVECOV_LDFLAGS) $? -o $@

%.nativecov.o: %.c
	$(CCSF) $(CFLAGS) $(NATIVECOV_FLAGS) $< -c -o $@


# SpecFuzz build
HONGGFUZZ_FLAGS := -L${HONGG_SRC}/libhfuzz/ -L${HONGG_SRC}/libhfcommon -lhfuzz -lhfcommon
SF_COMMON := --function-list $(CURDIR)/function_list.txt --enable-coverage -DNDEBUG
ifdef SF_COLLECT
	SF_COMMON := --collect $(CURDIR)/function_list.txt
endif
SF_FLAGS := $(SF_COMMON)
SF_LDFLAGS := $(SF_COMMON) $(HONGGFUZZ_FLAGS)

sf: $(addsuffix .sf.o, $(SRC))
	$(CCSF) $(LDFLAGS) $(SF_LDFLAGS) $? -o $@

%.sf.o: %.c
	$(CCSF) $(CFLAGS) $(SF_FLAGS) $< -c -o $@


# SLH pass
CCSLH = /usr/bin/clang-slh
CXXSLH = /usr/bin/clang-slh++
SLH_COMMON := --whitelist $(CURDIR)/$(WHITELIST) --whitelist-loads $(CURDIR)/loadlist.txt --whitelist-files $(CURDIR)/perf_function_list.txt
SLH_FLAGS := $(SLH_COMMON)
SLH_LDFLAGS := $(SLH_COMMON)

slh: $(addsuffix .slh.o, $(SRC))
	$(CCSLH) $(LDFLAGS) $(SLH_LDFLAGS) $? -o $@

%.slh.o: %.c
	$(CCSLH) $(CFLAGS) $(SLH_FLAGS) $< -c -o $@


# Patch with LFENCE based on SpecFuzz results
WHITELIST ?= whitelist.txt  # generated by SpecFuzz
PATCH_COMMON := --lfence --whitelist $(CURDIR)/$(WHITELIST) --whitelist-files $(CURDIR)/perf_function_list.txt
ifdef PATCH_BLACKLIST
	PATCH_COMMON += --lfence-branches-as-blacklist
endif
PATCH_FLAGS := $(PATCH_COMMON)
PATCH_LDFLAGS := $(PATCH_COMMON)

patched: $(addsuffix .patched.o, $(SRC))
	$(CCSLH) $(LDFLAGS) $(PATCH_LDFLAGS) $? -o $@

%.patched.o: %.c
	$(CCSLH) $(CFLAGS) $(PATCH_FLAGS) $< -c -o $@
